package cn.ibizlab.core.oauth2.config;

import cn.ibizlab.core.oauth2.service.impl.OAuth2TokenService;
import cn.ibizlab.core.oauth2.service.impl.OauthClientDetailsServiceImpl;
import cn.ibizlab.util.security.SSOAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.sql.DataSource;

/**
 * OAuth2授权认证服务：负责oauth模式下的用户认证及生成访问令牌
 */
@Configuration
@EnableAuthorizationServer
@ConditionalOnProperty(name = "ibiz.auth.security", havingValue = "oauth2", matchIfMissing = true)
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    DataSource dataSource;
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    OauthClientDetailsServiceImpl clientDetailsService;
    @Autowired
    UserDetailsService userDetailsService;
    @Autowired
    SSOAuthenticationFilter ssoAuthenticationFilter;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security){
        security.passwordEncoder(passwordEncoder);
        security
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("permitAll()")
                .allowFormAuthenticationForClients();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints){
        endpoints.authenticationManager(authenticationManager) //认证管理器
                 .userDetailsService(userDetailsService)//密码模式的用户信息管理
                 .tokenServices(tokenServices()) //令牌管理服务
                 .tokenStore(tokenStore()); //令牌存储模式
    }


    @Autowired
    @Lazy
    private RedisConnectionFactory redisConnectionFactory;

    @Value("${ibiz.cacheLevel:L1}")
    private String cacheLevel;

    @Bean
    public TokenStore tokenStore() {
        if("L1".equals(cacheLevel))
            return new JdbcTokenStore(dataSource);
        else
            return new RedisTokenStore(redisConnectionFactory);
    }

    @Bean
    public DefaultTokenServices tokenServices(){
        DefaultTokenServices tokenService = new OAuth2TokenService();
        tokenService.setClientDetailsService(clientDetailsService);
        tokenService.setSupportRefreshToken(true);
        tokenService.setTokenStore(tokenStore());
        return tokenService;
    }

}
